﻿using Pay.Core;
using Pay.Data;
using Pay.DTO;
using Pay.IService;
using Pay.TO;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Pay.Service {
    public class TokenUserService : ServiceBase, ITokenUserService, IDisposable {
        private IUnitOfWork _iUnitOfWork;
        private ITokenService _tokenService;
        private IMarketingTokenService _iMarketingTokenService;
        private IMerchantService _merchantService;
        public TokenUserService(IUnitOfWork iUnitOfWork, ITokenService tokenService, IMarketingTokenService iMarketingTokenService, IMerchantService merchantService) : base(iUnitOfWork) {
            _iUnitOfWork = iUnitOfWork;
            _tokenService = tokenService;
            _iMarketingTokenService = iMarketingTokenService;
            _merchantService = merchantService;
        }

        #region 后台管理
        /// <summary>
        /// 获得Token用户信息分页列表
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public PagedResult<token_user_dto> GetTokenUsers(TokenUserQuery query) {
            var q = from u in context.RedRecord
                        //join a in context.AuthInfos.Where(o => o.Status == CertifyStatus.Auth) on u.MerchantId equals a.MerchantId
                    join a in context.AuthInfos on u.MerchantId equals a.MerchantId
                    select new token_user_dto() {
                        id = u.Id,
                        merchant_id = u.MerchantId,
                        create_time_unix = u.Merchant.CreateTime,
                        total_horse_power = u.TotalHorsePower,
                        total_red_drill = u.TotalRedDrill,
                        consume_red_drill = u.ConsumeRedDrill,
                        invitation_code = u.InvitationCode,
                        invitation_num = u.InvitationCodeNum,
                        user_name = a.AccountName,
                        card_no = a.IdCard,
                        name = u.Merchant.Name,
                        mobile = u.Merchant.Mobile,
                        disabled = u.Merchant.Disabled,
                        is_platform = u.Merchant.IsPlatform,
                        user_type = u.Merchant.UserType,
                        user_type_value = u.Merchant.UserType != null ? ((int)u.Merchant.UserType).ToString() : ((int)UserType.user).ToString()
                    };
            var filter = PredicateBuilder.True<token_user_dto>();
            filter = filter.And(c => c.is_platform == false);
            if (!string.IsNullOrEmpty(query.name)) {
                filter = filter.And(o => o.name == query.name);
            }
            if (!string.IsNullOrEmpty(query.mobile)) {
                filter = filter.And(o => o.mobile == query.mobile);
            }

            if (!string.IsNullOrEmpty(query.disabled)) {
                bool value = query.disabled == "1" ? true : false;
                filter = filter.And(o => o.disabled == value);
            }
            if (!string.IsNullOrEmpty(query.begin_time)) {
                long value = DateTime.Parse(query.begin_time).ToUnix();
                filter = filter.And(o => o.create_time_unix >= value);
            }
            if (!string.IsNullOrEmpty(query.end_time)) {
                long value = DateTime.Parse(query.end_time).AddDays(1).ToUnix();
                filter = filter.And(o => o.create_time_unix <= value);
            }
            if (!string.IsNullOrEmpty(query.account_name)) {
                filter = filter.And(o => o.user_name == query.account_name);
            }
            if (!string.IsNullOrEmpty(query.id_card)) {
                filter = filter.And(o => o.card_no == query.id_card);
            }
            q = q.Where(filter);
            var rowsCount = q.Count();

            if (query.sort == 1)
                q = q.OrderByDescending(c => c.total_horse_power);
            else
                q = q.OrderByDescending(c => c.create_time_unix);
            var rows = q.Skip((query.page - 1) * query.size).Take(query.size).ToList();
            var result = new PagedResult<token_user_dto>(rows, rowsCount, query.page, query.size);
            return result;
        }

        /// <summary>
        /// 修改会员是否禁用状态
        /// </summary>
        /// <param name="merchant_id"></param>
        /// <param name="isDisabled"></param>
        /// <returns></returns>
        public int UpdateDisabled(long merchant_id, int isDisabled) {
            Merchant model = context.Merchants.FindById(merchant_id);
            model.Disabled = isDisabled == 1 ? true : false;
            if (model.Disabled == true) {//冻结，重置Token
                token_info_dto tokenInfo = new token_info_dto();
                var exp_dt = DateTime.Now.AddMinutes(1);
                string token = "Disabled";
                tokenInfo.access_token = token;
                tokenInfo.expires_in = 1;
                tokenInfo.expires_date = exp_dt;
                tokenInfo.id = merchant_id;
                _tokenService.Save(tokenInfo);


                //移出拓垦合伙人营销系统对应token
                _iMarketingTokenService.Remove(merchant_id);
            }
            int result = _iUnitOfWork.Commit("Merchant" + merchant_id);
            return result;
        }

        /// <summary>
        /// 获得会员信息
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public token_user_dto_ex GetTokenUser(long id, TokenUserPageQueryEx queryPageEx) {
            var result = new token_user_dto_ex();
            context.RedRecord.Find(id).ToDtoObject<token_user_dto>().ToCopyProperty(result);
            var merchant = _merchantService.Get(result.merchant_id);
            result.create_time_unix = merchant.create_time.ToUnix();
            result.is_face = merchant.is_face;
            result.face_time = merchant.face_time.ToString();
            if (merchant != null) {
                var parentMerchant = _merchantService.Get(merchant.parent_id);
                if (parentMerchant != null)
                    result.parent_mobile = parentMerchant.mobile;
            }

            var auth = _merchantService.GetAuth(result.merchant_id); //context.AuthInfos.Where(o => o.MerchantId == result.merchant_id && o.Status == CertifyStatus.Auth).FirstOrDefault();
            if (auth != null) {
                result.user_name = auth.account_name;
                result.card_no = auth.id_card;
            }
            //用户邀请记录
            var q1 = context.UserInvitationHis.Where(o => o.InvitedUserId == result.merchant_id);
            var rowsCount1 = q1.Count();
            var rows1 = q1.OrderByDescending(o => o.CreateTime).Skip((queryPageEx.page1 - 1) * queryPageEx.size1).Take(queryPageEx.size1).ToList().ToDtoList<user_invitation_his_dto>();

            if (rows1 != null && rows1.Count() > 0) {
                //List<long> merchantIdList = rows1.Select(o => o.user_id).ToList() ?? new List<long>();
                //List<AuthInfo> authInfoList = context.AuthInfos.Where(o => merchantIdList.Contains(o.MerchantId) && o.Status == CertifyStatus.Auth).ToList() ?? new List<AuthInfo>();
                foreach (var row in rows1) {
                    var authInfo = _merchantService.GetAuth(row.user_id);
                    //var authInfo = authInfoList.Where(o => o.MerchantId == row.user_id && o.Status == CertifyStatus.Auth).FirstOrDefault();
                    if (authInfo != null) {
                        row.account_name = authInfo.account_name;
                        row.id_card = authInfo.id_card;
                    }
                }
            }
            result.user_invitation_his_list = new PagedResult<user_invitation_his_dto>(rows1, rowsCount1, queryPageEx.page1, queryPageEx.size1);
            //用户转赠记录
            var q2 = context.UserRedTransferHis.Where(o => (o.UserId == result.merchant_id && o.IsShowTransferOut == true) || o.ReceiveUserId == result.merchant_id);
            var rowsCount2 = q2.Count();
            var rows2 = q2.OrderByDescending(o => o.CreateTime).Skip((queryPageEx.page2 - 1) * queryPageEx.size2).Take(queryPageEx.size2).ToList().ToDtoList<user_red_transfer_his>();
            result.user_red_transfer_his_list = new PagedResult<user_red_transfer_his>(rows2, rowsCount2, queryPageEx.page2, queryPageEx.size2);
            return result;
        }

        /// <summary>
        /// 获得当日用户邀请好友数量排行
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public PagedResult<token_user_invitation_info> GetTokenUserInvitationRanking(TokenUserInvitationQuery query) {
            DateTime beginTime = DateTime.Parse(query.begin_time);
            DateTime endTime = DateTime.Parse(query.end_time).AddDays(1).AddMilliseconds(-1);

            var userInvitationGroup = (from t in context.UserInvitationHis.Where(o => o.CreateTime >= beginTime && o.CreateTime <= endTime)
                                       group t by t.InvitedUserId into g
                                       select new {
                                           g.Key,
                                           Num = g.Count()
                                       }).Where(o => o.Num > 0).ToList();

            var q = from g in userInvitationGroup
                    join m in context.Merchants on g.Key equals m.Id into t1
                    from tm in t1.DefaultIfEmpty()
                    join a in context.AuthInfos.Where(o => o.Status == CertifyStatus.Auth) on g.Key equals a.MerchantId into t2
                    from ta in t2.DefaultIfEmpty()
                    select new token_user_invitation_info() {
                        user_id = g.Key,
                        name = tm != null ? tm.Name : "",
                        mobile = tm != null ? tm.Mobile : "",
                        user_name = ta != null && !string.IsNullOrEmpty(ta.AccountName) ? ta.AccountName : "",
                        invitation_num = g.Num
                    };
            var rowsCount = q.Count();
            var rows = q.OrderByDescending(c => c.invitation_num).Skip((query.page - 1) * query.size).Take(query.size).ToList();
            var result = new PagedResult<token_user_invitation_info>(rows, rowsCount, query.page, query.size);
            return result;
        }

        /// <summary>
        /// 获得当日邀请记录明细
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="time"></param>
        /// <returns></returns>
        public List<user_invitation_his_dto> GetTokenUserInvitationHis(long userId, string begin_time, string end_time) {
            DateTime beginTime = DateTime.Parse(begin_time);
            DateTime endTime = DateTime.Parse(end_time).AddDays(1).AddMilliseconds(-1);
            var result = context.UserInvitationHis.Where(o => o.InvitedUserId == userId && o.CreateTime >= beginTime && o.CreateTime <= endTime).ToList().ToDtoList<user_invitation_his_dto>();
            if (result != null && result.Count() > 0) {
                //List<long> merchantIdList = result.Select(o => o.user_id).ToList() ?? new List<long>();
                //List<AuthInfo> authInfoList = context.AuthInfos.Where(o => merchantIdList.Contains(o.MerchantId) && o.Status == CertifyStatus.Auth).ToList() ?? new List<AuthInfo>();
                foreach (var row in result) {
                    var authInfo = _merchantService.GetAuth(row.user_id); //var authInfo = authInfoList.Where(o => o.MerchantId == row.user_id && o.Status == CertifyStatus.Auth).FirstOrDefault();
                    if (authInfo != null) {
                        row.account_name = authInfo.account_name;
                        row.id_card = authInfo.id_card;
                    }
                }
            }
            return result;

        }

        private static readonly object objkey = new object();

        /// <summary>
        /// 增加用户马力
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="horsePower"></param>
        /// <returns></returns>
        public bool IncreaseUserHorsePower(long userId, int horsePower, int day, long sysUserId) {
            lock (objkey) {
                if (horsePower == 0)
                    throw new ServerErrorException("增加马力值必须大于0或小于0");
                //防止重复读
                using (var trans = context.Database.BeginTransaction()) {
                    try {
                        //增加总马力
                        RedRecord redRecord = context.RedRecord.Where(o => o.MerchantId == userId).FirstOrDefault();
                        if (horsePower < 0 && (horsePower + redRecord.TotalHorsePower < 30)) throw new ServerErrorException("减少的马力值已小于用户的初始马力");
                        redRecord.TotalHorsePower += horsePower;

                        //增加马力记录
                        UserSoupValueHis userSoupValueHis = new UserSoupValueHis() { SoupValue = horsePower, TaskType = ETaskType.Other, UserId = userId, CreateTime = DateTime.Now.ToUnix(), ItemId = sysUserId };
                        if (day > 0) {
                            var dt = DateTime.Now;
                            var cdt = dt.ToUnix();
                            var effdt = dt.AddDays(day).ToUnix();
                            userSoupValueHis.EffectiveTime = effdt;
                            //增加临时表
                            context.UserSoupValueSnap.Add(new UserSoupValueSnap { MerchantId = userId, TaskType = ETaskType.Other, CreateTime = cdt, EffectiveTime = effdt, SoupValue = horsePower });
                        }
                        context.UserSoupValueHis.Add(userSoupValueHis);

                        var result = _iUnitOfWork.Commit("RedRecord" + userId) > 0;
                        trans.Commit();
                        return result;
                    } catch (Exception ex) {
                        trans.Rollback();
                        throw ex;
                    }
                }
            }
        }

        /// <summary>
        /// 修改用户等级
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="userType"></param>
        /// <returns></returns>
        public bool UpdateUserType(long userId, int userType) {
            if (userType != (int)UserType.user && userType != (int)UserType.tokenMaker && userType != (int)UserType.tokenNodeMall
                && userType != (int)UserType.tokenCountyAgent && userType != (int)UserType.tokenCityAgent)
                throw new ServerErrorException("参数不正确");
            Merchant merchant = context.Merchants.FindById(userId);
            merchant.UserType = (UserType)userType;

            //if (userType != (int)UserType.user && !context.UserSoupValueHis.Exist(o => o.UserId == userId && o.TaskType == ETaskType.UserUpgrade)) {//第一次升级，增加用户马力值
            //    //增加总马力
            //    RedRecord redRecord = context.RedRecord.Where(o => o.MerchantId == userId).FirstOrDefault();
            //    redRecord.TotalHorsePower += 20;

            //    //增加马力记录
            //    UserSoupValueHis userSoupValueHis = new UserSoupValueHis() { SoupValue = 20, TaskType = ETaskType.UserUpgrade, UserId = userId, RedRecordId = redRecord.Id, CreateTime = DateTime.Now };
            //    context.UserSoupValueHis.Add(userSoupValueHis);
            //}

            //更新升级时间
            merchant.UpgradeTime = DateTime.Now;
            return _iUnitOfWork.Commit("Merchant" + merchant.Id, "Merchant" + merchant.MerchantNo) > 0;
        }

        /// <summary>
        /// 微信支付升级创客
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public bool TokenUpgradeMaker(long userId) {
            Merchant merchant = context.Merchants.FindById(userId);
            var dts = DateTime.Now;
            if ((int)merchant.UserType >= (int)UserType.tokenMaker) {//已是创客或以上级别，不再保存级别，但要保存支付订单
                var log = IocHelper.Get<ILogHelper>("info");
                log.Info("已是创客或以上级别，不再变更级别，但要保存支付订单,userId：" + userId);

                //增加398任务可以领取
                var item = context.TokenTaskUpgrade.Find(userId);
                if (item == null) {
                    item = new TokenTaskUpgrade { Id = userId, CreateTime = dts.ToUnix(), Status = 1 };
                    context.TokenTaskUpgrade.Add(item);
                }
                return true;
            } else {
                merchant.UserType = UserType.tokenMaker;
                //更新升级时间
                merchant.UpgradeTime = dts;

                //增加398任务可以领取
                var item = context.TokenTaskUpgrade.Find(userId);
                if (item == null) {
                    item = new TokenTaskUpgrade { Id = userId, CreateTime = dts.ToUnix(), Status = 1 };
                    context.TokenTaskUpgrade.Add(item);
                }

            }
            return true;
        }

        #endregion

        #region API
        #endregion
    }
}